/*
 * lexer.c
 *
 *  Created on: 24/07/2012
 *      Author: annibal
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "leitura.h"
#include "lexer.h"

void criaLexer(FILE *espec, Lexer *L) {
	int i;
	Automato *M;

	M = (Automato*) malloc(sizeof(Automato));
	criaAutomato(M, espec);

	L->AF = M;

	L->numTokens = leInteiro(espec);
	L->listaTokens = (char*) malloc(L->numTokens * sizeof(char));
	for (i = 0; i < L->numTokens; i++) {
		L->listaTokens[i] = leCaractere(espec);
	}

	criaTabelaTokens(espec, L);
	L->token = NULL;
}

void criaTabelaTokens(FILE *espec, Lexer *L) {
	int i, j, achou, fim = FALSE;
	Automato *M;
	char *nomeEstado, token;

	M = L->AF;
	L->tabelaTokens = (char**) malloc(M->numEstados * sizeof(char*));

	while (fim == FALSE) {
		nomeEstado = leString(espec);

		if (nomeEstado != NULL) {
			token = leCaractere(espec);

			achou = FALSE;
			for (i = 0; i < M->numEstados && achou == FALSE; i++) {
				if (strcmp(M->estados[i].nome, nomeEstado) == 0) {
					for (j = 0; j < L->numTokens && achou == FALSE; j++) {
						if (L->listaTokens[j] == token) {
							L->tabelaTokens[i] = L->listaTokens + j;
							achou = TRUE;
						}
					}
				}
			}
		} else {
			fim = TRUE;
		}
	}
}

void extraiToken(Lexer *L) {
	int i, achou = FALSE, fim = FALSE;
	Automato *M;
	Estado *proximo;

	M = L->AF;
	M->estadoAtual = M->estadoInicial;

	while (fim == FALSE) {
		if (*(M->leitor) == '\0') {
			fim = TRUE;
		} else {
			proximo = buscaTransicao(M);

			if (proximo != NULL) {
				M->estadoAtual = proximo;
				(M->leitor)++;
			} else {
				fim = TRUE;
			}
		}
	}

	if (M->estadoAtual->final == TRUE) {
		for (i = 0; i < M->numEstados && achou == FALSE; i++) {
			if (strcmp(M->estados[i].nome, M->estadoAtual->nome) == 0) {
				L->token = L->tabelaTokens[i];
				achou = TRUE;
			}
		}
	} else {
		L->token = NULL;
	}
}

char passaToken(Lexer *L) {
	char token;

	if (L->token != NULL) {
		token = *(L->token);
		L->token = NULL;
		return token;
	} else {
		return 0;
	}
}

void recebeTokenLexer(char token, Lexer *L) {
	int i, achou = FALSE;

	if (token == 0) {
		L->token = NULL;
	} else {
		for (i = 0; i < L->numTokens && achou == FALSE; i++) {
			if (L->listaTokens[i] == token) {
				achou = TRUE;
				L->token = L->listaTokens + i;
			}
		}
	}
}

void inicializaLexer(char* cadeia, Lexer *L) {
	L->AF->estadoAtual = L->AF->estadoInicial;
	L->token = NULL;
	L->AF->leitor = cadeia;
}
